﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;
using System.Diagnostics;
using System.IO;
using System.Threading;

namespace Ellanet
{
    class vmrunCLIWrapper
    {
        private string _vmrunPath = null;
        private string _hostType = null;
        private string _hostArguments = null;
        private string _hostUsername = null;
        private string _hostPassword = null;
        private string _guestUsername = null;
        private string _guestPassword = null;
        private string _PasswordSafeArguments = null;
        private string _vmrunCommand = null;
        private string vmrunArguments = null;

        public string PasswordSafeArguments
        {
            get
            {
                return _PasswordSafeArguments;
            }
        }

        public vmrunCLIWrapper(string vmrunPath, string hostType, string hostArguments, string hostUsername, string hostPassword, string guestUsername, string guestPassword, string vmrunCommand)
        {
            _vmrunPath = vmrunPath;
            _hostType = hostType;
            _hostArguments = hostArguments;
            _hostUsername = hostUsername;
            _hostPassword = hostPassword;
            _guestUsername = guestUsername;
            _guestPassword = guestPassword;
            _vmrunCommand = vmrunCommand;

            if (_hostArguments.Length > 0)
            {
                _hostArguments = String.Format(" {0}", _hostArguments);
            }

            BuildvmrunArguments();
        }

        private void BuildvmrunArguments()
        {
            _PasswordSafeArguments = String.Format("-T {0}{1}{2}{3} {4}", _hostType, _hostArguments, BuildHostCredentialsArguments(true), BuildGuestCredentialsArguments(true), _vmrunCommand);
            vmrunArguments = String.Format("-T {0}{1}{2}{3} {4}", _hostType, _hostArguments, BuildHostCredentialsArguments(false), BuildGuestCredentialsArguments(false), _vmrunCommand);
        }

        private string BuildHostCredentialsArguments(bool makeSafe)
        {
            if ((_hostUsername != null) && (_hostUsername.Trim().Length > 0) && (_hostPassword != null) && (_hostPassword.Trim().Length > 0))
            {
                if (makeSafe)
                {
                    return String.Format(" -u \"{0}\" -p \"{1}\"", _hostUsername, "%HOST_PASSWORD%");
                }
                else
                {
                    return String.Format(" -u \"{0}\" -p \"{1}\"", _hostUsername, _hostPassword);
                }
            }
            else
            {
                return String.Empty;
            }
        }

        private string BuildGuestCredentialsArguments(bool makeSafe)
        {
            if ((_guestUsername != null) && (_guestUsername.Trim().Length > 0) && (_guestPassword != null) && (_guestPassword.Trim().Length > 0))
            {
                if (makeSafe)
                {
                    return String.Format(" -gu \"{0}\" -gp \"{1}\"", _guestUsername, "%GUEST_PASSWORD%");
                }
                else
                {
                    return String.Format(" -gu \"{0}\" -gp \"{1}\"", _guestUsername, _guestPassword);
                }
            }
            else
            {
                return String.Empty;
            }
        }

        public bool ExecuteCommand(int timeout, out ArrayList standardOutput, out int exitCode)
        {
            standardOutput = new ArrayList();
            exitCode = -1;

            if (File.Exists(_vmrunPath))
            {
                vmrunInfoXmlWrapper infoXmlWrapper = new vmrunInfoXmlWrapper();
                Process vmrun = new Process();
                vmrun.StartInfo.FileName = _vmrunPath;
                vmrun.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
                vmrun.StartInfo.CreateNoWindow = true;
                vmrun.StartInfo.UseShellExecute = false;
                vmrun.StartInfo.RedirectStandardOutput = true;
                vmrun.StartInfo.Arguments = vmrunArguments;
                Debug.WriteLine(vmrun.StartInfo.Arguments);
                vmrun.Start();

                if (timeout > -1)
                {
                    while ((!vmrun.HasExited) && (vmrun.Responding) && (DateTime.Now.Subtract(vmrun.StartTime).TotalSeconds < timeout))
                    {
                        Thread.Sleep(250);
                    }
                }
                else
                {
                    vmrun.WaitForExit();
                }

                if (!vmrun.HasExited)
                {
                    vmrun.Close();
                    standardOutput.Add("Process timeout period has expired.");
                }
                else
                {
                    exitCode = vmrun.ExitCode;

                    while (vmrun.StandardOutput.Peek() > -1)
                    {
                        standardOutput.Add(vmrun.StandardOutput.ReadLine());
                    }
                }

                if ((exitCode == 0) && (standardOutput.Count == 0))
                {
                    standardOutput.Add("Command completed successfully.");
                }

                if (exitCode == 0)
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
            else
            {
                standardOutput.Add("Could not locate vmrun.exe. Please make sure the path specified is correct.");
                return false;
            }
        }

        public bool TestHostConnection(out string message)
        {
            ArrayList stdOut = null;
            int exitCode;
            _vmrunCommand = "list";
            BuildvmrunArguments();
            bool success = ExecuteCommand(60, out stdOut, out exitCode);
            message = null;

            foreach (string line in stdOut)
            {
                message += line;
            }

            return success;
        }
    }
}
